package com.gameproject.alltogether;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;

import com.gameproject.alltogether.util.IntersectUtils;

import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class GameView extends SurfaceView implements SurfaceHolder.Callback {

	private SpriteObject[] balls;

	private GameLogic mGameLogic;
	private ArrayBlockingQueue<InputObject> inputObjectPool;

	private Context context;
	private SoundPool soundPool;
	private MediaPlayer mp;
	
	private int touchDownX;
	private int touchDownY;
	private int touchUpX;
	private int touchUpY;

	private List<LineWall> walls = new ArrayList<LineWall>();
	
	public GameView(Context con) {
		super(con);
		context = con;
		getHolder().addCallback(this);
		balls = new SpriteObject[3];
		Random random = new Random();
		int maxWidth = 900;
		int maxHeight = 600;
		balls[0] = new SpriteObject(BitmapFactory.decodeResource(getResources(),
				R.drawable.ball), random.nextInt(maxWidth),
				random.nextInt(maxHeight), 1);
		balls[1] = new SpriteObject(BitmapFactory.decodeResource(getResources(),
				R.drawable.ball2), random.nextInt(maxWidth),
				random.nextInt(maxHeight), 2);
		balls[2] = new SpriteObject(BitmapFactory.decodeResource(getResources(),
				R.drawable.ball3), random.nextInt(maxWidth),
				random.nextInt(maxHeight), 3);
		mGameLogic = new GameLogic(getHolder(), this);
		createInputObjectPool();

		soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
		setFocusable(true);
	}

	private void createInputObjectPool() {
		inputObjectPool = new ArrayBlockingQueue<InputObject>(20);
		for (int i = 0; i < 20; i++) {
			inputObjectPool.add(new InputObject(inputObjectPool));
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		try {
			int hist = event.getHistorySize();
			if (hist > 0) {
				for (int i = 0; i < hist; i++) {
					InputObject input = inputObjectPool.take();
					input.useEventHistory(event, i);
					mGameLogic.feedInput(input);
				}
			}
			InputObject input = inputObjectPool.take();
			input.useEvent(event);
			mGameLogic.feedInput(input);
		} catch (InterruptedException e) {
		}
		try {
			Thread.sleep(16);
		} catch (InterruptedException e) {
		}
		return true;
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		mGameLogic.setGameState(GameLogic.RUNNING);
		mGameLogic.start();
		MediaPlayer mp = MediaPlayer.create(context, R.raw.background_music);
		mp.setLooping(true);
		mp.start();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		soundPool.release();
		mp.stop();
		mp.release();
	}

	@Override
	public void onDraw(Canvas canvas) {
		canvas.drawColor(Color.DKGRAY);
		for (int i = 0; i < 3; i++) {
			balls[i].draw(canvas);
		}
		for (LineWall wall : walls) {
			wall.draw(canvas);
		}
	}

	public void update(int adj_mov) {

		// check for balls colliding with the screen walls
		for (int i = 0; i < 3; i++) {
			if (balls[i].getY() > getHeight() - 50) {
				balls[i].setMoveY(-Constants.MOVE_RATE);
			}
			if (balls[i].getX() > getWidth() - 50) {
				balls[i].setMoveX(-Constants.MOVE_RATE);
			}
			if (balls[i].getY() < 50) {
				balls[i].setMoveY(Constants.MOVE_RATE);
			}
			if (balls[i].getX() < 50) {
				balls[i].setMoveX(Constants.MOVE_RATE);
			}
		}


		// check for collisions between the balls
		for (int i = 0; i < balls.length; i++) {
			for (int j = i+1; j < balls.length; j++) {
				if (i != j) {
					if (balls[i].collide(balls[j])) {
						double movexi = balls[i].getMoveX();
						balls[i].setMoveX(balls[j].getMoveX());
						balls[j].setMoveX(movexi);
						
						double moveyi = balls[i].getMoveY();
						balls[i].setMoveY(balls[j].getMoveY());
						balls[j].setMoveY(moveyi);
					}
				}
			}
		}
		
		for (int i = 0; i < balls.length; i++){
			for (LineWall wall : walls) {
				if (IntersectUtils.lineRectIntersects(wall.getInitX(), wall.getInitY(), 
						wall.getEndX(), wall.getEndY(), balls[i].getRectangle())){
					balls[i].setMoveX(-balls[i].getMoveX());
					balls[i].setMoveY(-balls[i].getMoveY());
				}
					
			}
		}

		// perform specific updates
		for (int i = 0; i < 3; i++) {
			balls[i].update(adj_mov);
		}

	}

	public void processMotionEvent(InputObject input) {
		if (input.action == InputObject.ACTION_TOUCH_DOWN){
			this.touchDownX = input.x;
			this.touchDownY = input.y;
		}
		else if (input.action == InputObject.ACTION_TOUCH_UP){
			this.touchUpX = input.x;
			this.touchUpY = input.y;
			this.walls.add(new LineWall(touchDownX, touchDownY, touchUpX, touchUpY));
		}
	}

	public void processKeyEvent(InputObject input) {

	}

	public void processOrientationEvent(float orientation[]) {

	}

	public void playsound(int sound_id) {
		soundPool.play(sound_id, 1.0f, 1.0f, 1, 0, 1.0f);
	}

}
